package com.jet.chat.server;

import java.util.Collection;
import java.util.HashMap;

import com.jet.chat.exception.ChatException;
import com.jet.chat.message.Message;


public class ChatChannel {
	private String channelName;
	private HashMap<String, ChatSession> chatChannel;
	
	public ChatChannel(String channelName) {
		this.channelName = channelName;
		this.chatChannel = new HashMap<String, ChatSession>();
	}

	public String getChannelName() {
		return channelName;
	}
	
	public synchronized Collection<ChatSession> getSessions() {
		//[DF] FIXME: it is not enough to synchronize only during modification of collection.
		//synchronization is still needed during reading of collection too.
		//also it is reasonable to block modification of this collection for outer classes through
		// Collections.unmodifiableCollection
		return chatChannel.values();
	}
	
	public synchronized ChatSession getSession(String username) {
		//[DF] FIXME: it is not enough to synchronize only during modification of collection.
		//synchronization is still needed during reading of collection too.
		return chatChannel.get(username);
	}
	
	public void addSession(ChatSession chatSession) throws ChatException {
		// [DF] TODO: synchronized is not needed during message send. In your situation network packet 
		// blocking all of your chatChannel works.
		// it is enough to synchronize during
		// update of chatChannel.
		for (ChatSession existedSession : getSessions()) {
			existedSession.getWriter().write(new Message("server > " + chatSession.getUsername() + " entered channel"));
		}
		chatSession.getWriter().write(new Message("server > you entered channel '" + channelName + "'"));
		synchronized(chatChannel) {
			chatChannel.put(chatSession.getUsername(), chatSession);
		}
	}
	
	public void removeSession(ChatSession chatSession) {
		// [DF] TODO: synchronized is not needed during message send. it is enough to synchronize during
		// update of chatChannel.
		try {
			chatSession.getWriter().write(new Message("server > you leaved channel '" + channelName + "'"));
		} catch (ChatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		synchronized(chatChannel) {
			chatChannel.remove(chatSession.getUsername());
		}
		for (ChatSession existedSession : getSessions()) {
			try {
				existedSession.getWriter().write(new Message("server > " + chatSession.getUsername() + " leaved channel"));
			} catch (ChatException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
